package org.qdao;

import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
 * 
 * @author 譚元吉
 * @since 2010/02/06 11:00:50
 */
public class DefaultEntityDao<T> implements InvocationHandler, IEntityDao<T> {

	private IDBEngine dbEngine;

	private PreparedStatement pstmt;

	private ResultSet rs;

	private Class<?> entity;

	private Logger logger = Logger.getLogger("OracleEntityDaoLogger");

	private String sql = null;

	@SuppressWarnings("unused")
	private boolean isLogger = true;

	public DefaultEntityDao(IDBEngine dbEngine, Class<?> entity) {
		this.dbEngine = dbEngine;
		this.entity = entity;
	}

	public DefaultEntityDao(IDBEngine dbEngine, Class<?> entity,
			boolean isLogger) {
		this.dbEngine = dbEngine;
		this.entity = entity;
		this.isLogger = isLogger;
	}

	public IDBEngine getDBEngine() {
		return this.dbEngine;
	}

	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {

		// before invoke log message
		logInfo("[invoking --> " + method.toGenericString() + ']');
		logInfo("[return type --> " + method.getGenericReturnType() + ']');

		Object result = method.invoke(this, args);

		// log the sql
		if (sql != null && sql.trim().length() != 0) {
			logInfo("{\r\n\t" + sql + "\r\n}");
		}

		// after invoke log message
		logInfo("[invoke successfully !]");
		logInfo("[return value --> " + result + ']');

		close();
		// after close the resource log message
		logInfo("[statement & resultset close successfully!]");
		dbEngine.dispose();

		// after dispose the engine log message
		logInfo("[DBEngine close successfully!]");
		return result;
	}

	public Integer count() {
		TableDescriptor table = dbEngine.getTableDescriptor(entity);
		int result = -1;
		sql = "SELECT COUNT(*) FROM " + table.name;
		try {
			pstmt = getDBEngine().getConnection().prepareStatement(sql);
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		try {
			rs = pstmt.executeQuery();
			if (rs.next()) {
				result = rs.getInt(1);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return result;
	}

	public Integer count(String sqlPart) {
		TableDescriptor table = dbEngine.getTableDescriptor(entity);
		int result = -1;
		sql = "SELECT COUNT(*) FROM " + table.name + " WHERE " + sqlPart;
		try {
			pstmt = getDBEngine().getConnection().prepareStatement(sql);
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		try {
			rs = pstmt.executeQuery();
			if (rs.next()) {
				result = rs.getInt(1);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return result;
	}

	public boolean connect() {
		return false;
	}

	public boolean create() {
		TableDescriptor table = dbEngine.getTableDescriptor(entity);
		sql = getCreateTigger(table);
		try {
			pstmt = getDBEngine().getConnection().prepareStatement(sql);
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		try {
			pstmt.executeUpdate();
			return true;
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return false;
	}

	public boolean delete(T key) {
		return false;
	}

	public boolean delete(List<T> data) {
		// TODO Auto-generated method stub
		return false;
	}

	public boolean drop() {
		return false;
	}

	public boolean exist() {
		return false;
	}

	public boolean lock(boolean share) {
		// TODO Auto-generated method stub
		return false;
	}

	public boolean lock(int timeout) {
		// TODO Auto-generated method stub
		return false;
	}

	public boolean insert(List<?> dtos) {
		// TODO Auto-generated method stub
		return false;
	}

	public boolean insert(T dto) {
		// TODO Auto-generated method stub
		return false;
	}

	public T lock(T key) {
		return null;
	}

	public T lock(T key, int timeout) {
		return null;
	}

	public List<T> lock(String sqlPart, int timeout) {
		// TODO Auto-generated method stub
		return null;
	}

	public List<T> lock(String sqlPart) {
		// TODO Auto-generated method stub
		return null;
	}

	public boolean match(Class<? extends T> table) {
		// TODO Auto-generated method stub
		return false;
	}

	public T selectByPrimaryKey(Serializable key) {
		return null;
	}

	public List<T> select() {
		return null;
	}

	public boolean drop(boolean cascade) {
		// TODO Auto-generated method stub
		return false;
	}

	public List<T> select(IFetchHandler<T> filter) {
		return null;
	}

	public List<T> select(String sqlPart) {
		return null;
	}

	public List<T> select(String sqlPart, IFetchHandler<T> filter) {
		return null;
	}

	public T update(T key) {
		return null;
	}

	public boolean update(List<T> data) {
		// TODO Auto-generated method stub
		return false;
	}

	public void close() {
		if (pstmt != null) {
			try {
				pstmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * log the information
	 * 
	 * @author tan
	 * @param msg
	 * 
	 *            2010/02/06 10:58:14
	 */
	private void logInfo(String msg) {
		logger.log(Level.INFO, msg);
	}

	/**
	 * CREATE THE TABLE'S TIGGER
	 * 
	 * @author tan
	 * @param table
	 * 
	 */
	private String getCreateTigger(TableDescriptor table) {
		StringBuffer buf = new StringBuffer("CREATE TABLE ");
		// add the table name
		buf.append(table.name + "(\r\n");
		for (int i = 0; i < table.columns.length; i++) {
			// add the column's name
			buf.append("\t" + table.columns[i].name + ' ')
			// add the column's type
					.append(table.columns[i].type);
			// add the column's length
			if (table.columns[i].length != -1) {
				buf.append("(" + table.columns[i].length + ") ");
			} else {
				buf.append(' ');
			}
			// add the column's nullable
			if (!table.columns[i].nullable) {
				buf.append("NOT NULL");
			}

			// add the comma
			if (i == table.columns.length - 1 && table.primaryKeys.length == 0) {
				buf.append("\r\n");
			} else {
				buf.append(",\r\n");
			}
		}

		// add the constraint for primary key
		if (table.primaryKeys.length != 0) {
			buf.append("\tCONSTRAINT PK_").append(table.name).append(
					" PRIMARY KEY (");
		}
		// add the primary key
		for (int i = 0; i < table.primaryKeys.length; i++) {
			if (i != table.primaryKeys.length - 1) {
				buf.append(table.primaryKeys[i]).append(',');
			} else {
				buf.append(table.primaryKeys[i]).append(")\r\n");
			}
		}
		// close the DDLｓ language
		buf.append(')');
		// add the comment
		if (table.description != null && !"".equals(table.description)) {
			buf.append("\r\n/\r\nCOMMENT ON TABLE ").append(table.name).append(
					" IS ").append("'").append(table.description).append(
					"'\r\n/");
		} else {
			buf.append("\r\n");
		}
		for (int i = 0; i < table.columns.length; i++) {
			if (table.columns[i].description != null
					&& !"".equals(table.columns[i].description)) {
				buf.append("\r\nCOMMENT ON COLUMN  ").append(table.name)
						.append(".").append(table.columns[i].name).append(
								" IS ").append("'").append(
								table.columns[i].description).append("'\r\n/");
			}
		}
		return buf.toString();
	}

	public boolean deletePart(String sqlPart) {
		// TODO Auto-generated method stub
		return false;
	}

	public List<T> selectNative(String sql) {
		// TODO Auto-generated method stub
		return null;
	}

	public T select(T key) {
		// TODO Auto-generated method stub
		return null;
	}

	public List selectNative(String sql, boolean isReturnList) {
		// TODO Auto-generated method stub
		return null;
	}

	public T selectByPrimaryKey(Object... objects) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<?> script(String script) {
		// TODO Auto-generated method stub
		return null;
	}

}
